package com.sicurezza.nfcrypto;

import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.spec.DHParameterSpec;

import android.app.Activity;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcAdapter.OnNdefPushCompleteCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.view.Menu;
import android.widget.TextView;
import android.widget.Toast;

public class KeyCreationActivity extends Activity implements OnNdefPushCompleteCallback,CreateNdefMessageCallback {
	
	private byte[] clientPubKey;
	private byte[] otherPubKey;
	private TextView textView;
	private KeyAgreement ClientKeyAgree;
	private static final String TAG = "KeyCreationActivity";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		NfcAdapter mNfcAdapter;
		DHParameterSpec dhSkipParamSpec;
        AlgorithmParameterGenerator paramGen;
		setContentView(R.layout.activity_key_creation);
		mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if (mNfcAdapter == null || !mNfcAdapter.isEnabled() || !mNfcAdapter.isNdefPushEnabled()) {
            Toast.makeText(this, "NFC o Android Beam non disponibili", Toast.LENGTH_LONG).show();
            Log.e(TAG, "NFC o android beam non attivo");
            finish();
            return;
        }
		try {
			paramGen = AlgorithmParameterGenerator.getInstance("DH");
			paramGen.init(512);
			AlgorithmParameters params = paramGen.generateParameters();
			dhSkipParamSpec = (DHParameterSpec)params.getParameterSpec(DHParameterSpec.class);
			Toast.makeText(this, R.string.generation_key, Toast.LENGTH_LONG).show();
			KeyPairGenerator ClientKpairGen = KeyPairGenerator.getInstance("DH");
			ClientKpairGen.initialize(dhSkipParamSpec);
			KeyPair ClientKpair = ClientKpairGen.generateKeyPair();
			ClientKeyAgree = KeyAgreement.getInstance("DH");
	        ClientKeyAgree.init(ClientKpair.getPrivate());
	        clientPubKey = ClientKpair.getPublic().getEncoded();
	        Log.v(TAG, "Completata la prima parte del keypair");
	        
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidParameterSpecException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidAlgorithmParameterException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
        mNfcAdapter.setNdefPushMessageCallback(this, this);
        mNfcAdapter.setOnNdefPushCompleteCallback(this,this);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.menu_key_creation, menu);
		return true;
	}

	@Override
	public void onNdefPushComplete(NfcEvent event) {

        try {
        	Log.v(TAG, "Inizia l'ultima parte del KeyAgreement");
        	X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(otherPubKey);
			KeyFactory ClientKeyFac = KeyFactory.getInstance("DH");
			x509KeySpec = new X509EncodedKeySpec(otherPubKey);
			PublicKey bobPubKey = ClientKeyFac.generatePublic(x509KeySpec);
			System.out.println("Client: Execute PHASE1 ...\n");
		    ClientKeyAgree.doPhase(bobPubKey, true);
	        SecretKey ClientAesKey = ClientKeyAgree.generateSecret("AES");
	        Log.v(TAG, "Ultima parte terminata, si passa alla scelta del contatto");
	        Intent contactPickerIntent = new Intent();
	        contactPickerIntent.setClassName("com.progettoSicurezza.nfcrypto", "ContactPickerActivity");
	        contactPickerIntent.putExtra("encodedKey", ClientAesKey.getEncoded());
	        startActivity(contactPickerIntent);
	        
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalStateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public NdefMessage createNdefMessage(NfcEvent event) {
		NdefMessage sent = null;
		sent = new NdefMessage(new NdefRecord(NdefRecord.TNF_UNKNOWN, null, null, clientPubKey));
		textView.setText(R.string.key_sent);
		return sent;
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		 if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
			 Log.v(TAG, "Trovato un nuovo Android Beamable device");
			 processIntent(getIntent());
		 }
	}

	private void processIntent(Intent intent) {
		Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
		NdefMessage toBeParsed = (NdefMessage) rawMsgs[0];
		otherPubKey = toBeParsed.getRecords()[0].getPayload();
		
	}

}
